package com.treeroot.treenet.protocol.udp;

import com.treeroot.treenet.enums.ProtocolTypeMenu;
import com.treeroot.treenet.protocol.BaseProtocolHandle;
import com.treeroot.treenet.protocol.ConnectDataCallback;
import com.treeroot.treenet.protocol.abs.udp.AbsUdpConnection;
import com.treeroot.treenet.protocol.abs.udp.BaseUdpVo;
import com.treeroot.treenet.strategy.ProtocolStrategyHandle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.function.Consumer;

/**
 * Create By TreeRoot
 * Create Time: 2023/12/18 03:44
 * Class Name: HandleUdpProtocol
 * Description:
 * UDP协议处理器
 * 1KB（千字节）等于1024个字节(字符)
 * 在UTF-8编码中，一个中文字符通常占用3个字节
 * 1字节（Byte）等于8个比特（Bit）
 *
 * @author TreeRoot
 */

public class HandleUdpProtocol extends AbsUdpConnection implements BaseProtocolHandle<BaseUdpVo>,
        ProtocolStrategyHandle {
    private static final Logger log = LoggerFactory.getLogger(HandleUdpProtocol.class);

    @Override
    public void handleRequest(ProtocolTypeMenu protocolType) {
        log.info("开始处理>>【HandleUdpRequest.handleRequest】");
        this.handleRequest(this::acceptConnection);
        log.info("结束处理>>【HandleUdpRequest.handleRequest】");
    }

    @Override
    public void acceptConnection(BaseUdpVo baseUdpVo) {
        Selector selector = baseUdpVo.getSelector();
        DatagramChannel datagramChannel = baseUdpVo.getDatagramChannel();
        //1.接受客户端连接请求
        try {
            //2.设置为非阻塞模式
            datagramChannel.configureBlocking(false);
            //3.注册选择器，指定监听事件为 OP_READ(读取数据 读就绪)
            datagramChannel.register(selector, SelectionKey.OP_READ);
            readDataFromClient(datagramChannel.keyFor(selector),()-> System.out.println("客户端关闭连接"));
            // 确保下一次仍然关注 OP_READ 事件
            datagramChannel.keyFor(selector).interestOps(SelectionKey.OP_READ);
        } catch (Exception e) {
            log.warn("HandleUdpRequest.handleRequest: 无法创建 ServerSocket", e);
        }
    }

    @Override
    public void readDataFromClient(SelectionKey key, ConnectDataCallback connectDataCallback) {
        log.info("开始处理===>>");
        DatagramChannel datagramChannel = (DatagramChannel) key.channel();
        try {
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 64);
            SocketAddress receive = datagramChannel.receive(byteBuffer);
            byteBuffer.flip();
            String messageFromRemote = new String(byteBuffer.array(), 0, byteBuffer.limit());
            log.info("客户端地址:{}===接收到的数据是{}", receive, messageFromRemote);
            byteBuffer.clear();
            //5. 发送端数据
            String message = "你好,我是UDP服务端,现在的时间是：" + new Date();
            ByteBuffer allocate = ByteBuffer.allocate(message.getBytes().length);
            allocate.put(message.getBytes(StandardCharsets.UTF_8));
            allocate.flip();
            datagramChannel.send(allocate, receive);
        } catch (Exception e) {
            log.error("HandleUdpRequest.readDataFromClient", e);
        } finally {
            // 不在这里关闭 DatagramChannel，而是在资源释放的地方关闭
            log.info("本次结束处理===>>");
        }
    }

    @Override
    public void handleRequest(Consumer<BaseUdpVo> acceptConnectionConsumer) {
        super.handleRequest(acceptConnectionConsumer);

    }

    @Override
    public void acceptBefore(BaseUdpVo baseUdpVo) {

    }

    @Override
    public void acceptAfter(BaseUdpVo baseUdpVo) {

    }
}
